package seatiger.tomcat.catalina.core;

import seatiger.tomcat.catalina.*;
import seatiger.tomcat.catalina.util.LifecycleSupport;
import seatiger.tomcat.util.StringManager;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * 服务器组件 包含多个服务
 * 提供统一的启动和初始化
 */
public class StandardServer implements Server, Lifecycle {

    private static final String info =
            "seatiger.tomcat.catalina.core.StandardServer/1.0";

    private LifecycleSupport lifecycle = new LifecycleSupport(this);

    private boolean started = false;
    private boolean initialized = false;

    private List<Service> services = new ArrayList<>(1);



    /**
     * 监听是否有shutdown 命令
     */
    private int port = 8005;


    private  String shutdown = "SHUTDOWN";

    private static final StringManager sm =
            StringManager.getManager(Constants.PACKAGE_CORE);

    @Override
    public void addLifecycleListener(LifecycleListener listener) {
        lifecycle.addLifecycleListener(listener);
    }

    @Override
    public List<LifecycleListener> findLifecycleListeners() {
        return lifecycle.findLifecycleListeners();
    }

    @Override
    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycle.removeLifecycleListener(listener);
    }

    @Override
    public void start() throws LifecycleException {
        if (started){
            throw new LifecycleException(sm.getString("standardServer.start.started"));
        }
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;
        synchronized (services){
            startComponents(services.toArray());
        }
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
    }

    @Override
    public String getInfo() {
        return info;
    }

    @Override
    public void addService(Service service) {
        service.setServer(this);
        synchronized (services) {
            services.add(service);
            if (initialized){
                try {
                    service.initialize();
                }catch (LifecycleException e){
                    e.printStackTrace(System.err);
                }
            }
            if (started){
                try {
                    startComponents(service);
                } catch (LifecycleException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void initialize() throws LifecycleException {
        if (initialized){
            throw new LifecycleException (sm.getString("standardServer.initialize.initialized"));
        }
        initialized = true;
        for (Service service: services){
            service.initialize();
        }
    }

    @Override
    public void stop() throws LifecycleException {
        if (!started){
            throw new LifecycleException(sm.getString("standardServer.stop.notStarted"));
        }
        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;
        stopComponents(services.toArray());
        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
    }

    @Override
    public void await() {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(port);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
        Socket socket = null;
        InputStream inputStream = null;
        while (true){
            try {
                socket = serverSocket.accept();
                inputStream = socket.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            Scanner scanner = new Scanner(inputStream);
            try {
                if (scanner.hasNext()){
                    String line = scanner.nextLine();
                    if (shutdown.equals(line)){
                        break;
                    }
                }
            }finally {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        try {
            serverSocket.close();
        } catch (IOException e) {
        }
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void setShutdown(String shutdown) {
        this.shutdown = shutdown;
    }

    @Override
    public List<Service> findServices() {
        return services;
    }
}
